package com.tianyadu.mmall.conf;

import com.tianyadu.mmall.filter.TimeFilter;
import com.tianyadu.mmall.interceptor.TimeInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

/**
 * 静态资源加载配置，注册第三方过滤器
 *
 * @author xueyj
 * @date 2019-10-08 16:56
 */
@Configuration
public class ServletContextConfig extends WebMvcConfigurationSupport {

    //    以下WebMvcConfigurerAdapter 比较常用的重写接口
    //    /** 解决跨域问题 **/
    //    public void addCorsMappings(CorsRegistry registry) ;
    //    /** 添加拦截器 **/
    //    void addInterceptors(InterceptorRegistry registry);
    //    /** 这里配置视图解析器 **/
    //    /** 视图跳转控制器 **/
    //    void addViewControllers(ViewControllerRegistry registry);
    //    void configureViewResolvers(ViewResolverRegistry registry);
    //    /** 配置内容裁决的一些选项 **/
    //    void configureContentNegotiation(ContentNegotiationConfigurer configurer);
    //    /** 视图跳转控制器 **/
    //    void addViewControllers(ViewControllerRegistry registry);
    //    /** 静态资源处理 **/
    //    void addResourceHandlers(ResourceHandlerRegistry registry);
    //    /** 默认静态资源处理器 **/
    //    void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer);

    @Autowired
    private TimeInterceptor timeInterceptor;

    /**
     * 若继承了WebMvcConfigurationSupport，则在yml中配置的相关内容会失效。
     * 需要重新指定静态资源
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
        super.addResourceHandlers(registry);
    }

    /**
     * 配置servlet处理
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    /**
     * 将定义拦截器加入到spring拦截器链
     *
     * @param registry 拦截器注册器
     * @return void
     * @author xueyj
     * @date 2019/9/21-16:22
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //  添加注册超时拦截器
        registry.addInterceptor(timeInterceptor);
    }

    /**
     * 申明密码加密方式
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    /**
     * 将第三方过滤器，加载到spring容器中
     *
     * @param
     * @return org.springframework.boot.web.servlet.FilterRegistrationBean
     * @author xueyj
     * @date 2019/9/21-16:23
     */
    @Bean
    public FilterRegistrationBean timeFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        TimeFilter timeFilter = new TimeFilter();
        registrationBean.setFilter(timeFilter);
        List<String> urls = new ArrayList<>();
        //  s所有路径都进行过滤
        urls.add("/*");
        registrationBean.setUrlPatterns(urls);
        return registrationBean;
    }

    /**
     * jpa懒加载异常
     *
     * @return org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
     * @author xueyj
     */
    @Bean
    public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
        return new OpenEntityManagerInViewFilter();
    }

    /**
     * 注册Spring data jpa pageable的参数分解器
     *
     * @param argumentResolvers
     * @return void
     * @author xueyj
     * @date 2019/9/21-23:59
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        // 注册Spring data jpa pageable的参数分解器
        argumentResolvers.add(new PageableHandlerMethodArgumentResolver());
    }

    /**
     * 异步请求相关配置
     *
     * @param configurer 异步请求配置
     * @return void
     * @author xueyj
     * @date 2019/9/29-16:28
     */
    // @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        //  注册使用主线程调用子线程的方式异步处理请求
        CallableProcessingInterceptor callableinterceptors = new CallableProcessingInterceptor() {
        };
        configurer.registerCallableInterceptors(callableinterceptors);

        //  注册使用DeferredResult请求方式的异步处理请求
        DeferredResultProcessingInterceptor deferredResultInterceptors = new DeferredResultProcessingInterceptor() {
        };
        configurer.registerDeferredResultInterceptors(deferredResultInterceptors);

        //  设置超时时间,如线程阻塞或挂掉无响应，http请求默认返回，释放本次请求资源
        configurer.setDefaultTimeout(2000);
        //
        AsyncTaskExecutor taskExecutor = new AsyncTaskExecutor() {
            @Override
            public void execute(Runnable runnable, long l) {

            }

            @Override
            public Future<?> submit(Runnable runnable) {
                return null;
            }

            @Override
            public <T> Future<T> submit(Callable<T> callable) {
                return null;
            }

            @Override
            public void execute(Runnable runnable) {

            }
        };
        //  设置线程池信息，若使用Callable方式，采用默认spring简单线程池，不会重用线程，每次调用都会新开一个线程
        configurer.setTaskExecutor(taskExecutor);
    }

}